package calc

trait Arithmetic{
  type T

  def plus: (T, T) => T
  def minus: (T, T) => T
  def uminus: (T) => T
  def multiply: (T, T) => T
  def divide: (T, T) => T
  def number(s: String): T
}

trait DoubleArithmetic extends Arithmetic {
  type T = Double
  def plus = _ + _
  def minus = _ - _
  def uminus = -_
  def multiply = _ * _
  def divide = _ / _
  def number(s: String) = s.toDouble

  def nextNumber(s: String): Option[String] = """\d+(\.\d+)?""".r.findPrefixOf(s)
}

trait IntegerArithmetic extends Arithmetic {
  type T = Int
  def plus = _ + _
  def minus = _ - _
  def uminus = -_
  def multiply = _ * _
  def divide = _ / _
  def number(s: String) = s.toInt
  
  def nextNumber(s: String): Option[String] = """\d+""".r.findPrefixOf(s)
}

case class Hex(val value: Int) {
  def +(h: Hex) = new Hex(value + h.value)
  def -(h: Hex) = new Hex(value - h.value)
  def *(h: Hex) = new Hex(value * h.value)
  def /(h: Hex) = new Hex(value / h.value)
  def unary_-() = new Hex(-value)
}
  
trait HexArithmetic extends Arithmetic {
  type T = Hex
  def plus = _ + _
  def minus = _ - _
  def uminus = -_
  def multiply = _ * _
  def divide = _ / _
  def number(s: String) = new Hex(Integer.parseInt(s, 16))
  
  def nextNumber(s: String): Option[String] = """[\da-fA-F]+""".r.findPrefixOf(s)
}
